package controllers;

import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import models.Jogador;
import models.Jogo;
import models.cartas.FabricaCarta;
import models.sala.Sala;
import models.sala.Sistema;

import org.codehaus.jackson.node.ObjectNode;

import play.libs.Json;
import play.mvc.Controller;
import play.mvc.Result;
import socket.Notificador;
import socket.ServidorNotificacao;
import views.html.index2;
import dao.DAOJogador;

public class UnoController extends Controller {

	private static Map<String, Jogo> jogos = new HashMap<>();
	public static Sistema sistema = new Sistema();
	
	public static Result iniciarNotificador() {
		Thread servidorNotificacao = new Thread(new ServidorNotificacao());
		servidorNotificacao.start();
		
		ObjectNode json = Json.newObject();
		json.put("info", "Chamada para iniciar o notificador realizada.");
		return ok(json);
	}
	
	
	public static Result autenticar(String login, String senha) {

		ObjectNode json = Json.newObject();

		Jogador jogador = new Jogador();
		jogador.email = login;
		jogador.senha = senha;

		DAOJogador dao = new DAOJogador();
		try {
			jogador = dao.autenticar(jogador);
			if (jogador != null) {

				//adiciona o jogador no 'sistema'
				sistema.addJogador(jogador);
				
				return ok(Json.toJson(jogador));
			} else {
				json.put("erro", "Login e/ou senha errada.");
			}
		} catch (Exception e) {
			e.printStackTrace();
			json.put("erro", e.getMessage());
		}

		return ok(json);
	}


	public static Result salas() {
		ObjectNode json = Json.newObject();

		Collection<Sala> salas = sistema.verSala();
		Collection<String> nomeSalas = new ArrayList<>();

		for(Sala s : salas){
			nomeSalas.add(s.nome);
		}

		if (!nomeSalas.isEmpty()) {
			return ok(Json.toJson(nomeSalas));
		} else {
			json.put("info", "Não existe sala no sistema.");
		}

		return ok(json);

	}


	public static Result jogadores(String sala) {
		ObjectNode json = Json.newObject();

		Sala s = sistema.buscarSala(sala);
		if (s != null) {
			List<Jogador> jogadores = s.jogadores;
			return ok(Json.toJson(jogadores));
		} else {
			json.put("erro", "A sala não foi encontrada;");
		}

		return ok(json);

	}
	
	
	public static Result criarSala(int idJogador, String sala, int qtMax) {
		ObjectNode json = Json.newObject();

		System.out.println("Sala:["+ sala +"]\tmqximo: ["+ qtMax +"]");
		Jogador jogador = sistema.buscarJogador(idJogador);
		System.out.println(jogador);
		
		if (sistema.criarSala(sala, qtMax, jogador)) {
			json.put("sucesso", "A sala foi criada.");
		} else {
			json.put("erro", "A sala nao foi criada.");
		}

		return ok(json);
	}
	
	
	public static Result entrarSala(int idJogador, String nomeSala) {
		ObjectNode json = Json.newObject();
		
		Jogador jogador = sistema.buscarJogador(idJogador);
		
		if (sistema.entrarSala(nomeSala, jogador)) {
			Sala sala = sistema.buscarSala(nomeSala);
			List<Jogador> jogadores = sala.jogadores;
			
			for(Jogador j : jogadores){
				j.notificar2("jogadores");
			}
			
			return ok(Json.toJson(sala));
		}
		
		json.put("erro", "A sala ja esta cheia.");
		
		return ok(json);
	}
	

	public static Result sairSala(int idJogador) {
		ObjectNode json = Json.newObject();
		
		Jogador jogador = sistema.buscarJogador(idJogador);
		Sala sala = sistema.sairSala(jogador);
		if (sala != null) {
			
			for (Jogador outroJogador : sala.jogadores) {
				outroJogador.notificar2("jogadores");
			}
			
			json.put("sucesso", "O jogador foi retirado da sala.");
		} else {
			json.put("erro", "O jogador nao saiu da sala.");
		}
		
		return ok(json);
	}
	
	public static Result sair(int idJogador) {
		ObjectNode json = Json.newObject();
		
		Jogador jogador = sistema.buscarJogador(idJogador);
		jogador.fecharNotificador();
		
		Sala sala = sistema.sairSala(jogador);
		sistema.removerJogador(jogador);
		
		if (sala != null) {
			
			for (Jogador outroJogador : sala.jogadores) {
				outroJogador.notificar2("jogadores");
			}
			
			json.put("sucesso", "O jogador saiu.");
		} else {
			json.put("erro", "O jogador nao saiu do sistema.");
		}
		
		return ok(json);
	}
	
	
/*
 * Controle do jogo
 * */
	
	public static Result iniciarJogo(String nomeSala) {
		ObjectNode json = Json.newObject();
		Sala sala = sistema.buscarSala(nomeSala);
		
		if (sala != null) {
			Jogo jogo = new Jogo(sala.jogadores);
			for (Jogador jogador : sala.jogadores) {
				jogador.notificar2("iniciarJogo");
			}
			
			jogos.put(sala.nome, jogo);
			
			return ok(Json.toJson(jogo.getStatus()));
		}

		json.put("erro", "O jogador nao saiu do sistema.");
		return ok(json);
	}
	
	
	public static Result statusJogo(String nomeSala) {
		
		ObjectNode json = Json.newObject();
		
		Sala sala = sistema.buscarSala(nomeSala);
		Jogo jogo = jogos.get(sala.nome);
		
		if (jogo != null) {
			return ok(Json.toJson(jogo.getStatus()));
		} else {
			json.put("erro", "Não foi encontrado jogo para a sala informada.");
		}
		
		return ok(json);
	}
	
	
	public static Result jogarCarta(int idJogador, String nomeSala, String carta, String cor) {
		
		ObjectNode json = Json.newObject();
		
		Sala sala = sistema.buscarSala(nomeSala);
		Jogador jogador = sistema.buscarJogador(idJogador);
		Jogo jogo = jogos.get(sala.nome);
		
		if (jogo != null) {
			if (jogo.realizarJogada(jogador, FabricaCarta.getInstance(carta), Jogo.TIPO_JOGADA_EMPRILHAR)) {
				for (Jogador jogador_ : sala.jogadores) {
					jogador_.notificar2("jogo");
				}
				return ok(Json.toJson(jogo.getStatus()));
			}
			json.put("erro", "A jogada não foi realizada, pois eh inválida. Possiveis erros: Jogador não possui carta, a carta não pode ser jogada, o jogador não está na sala, não é a vez do jogador.");
		} else {
			json.put("erro", "Não foi encontrado jogo para a sala informada.");
		}
		
		return ok(json);
	}
	
	public static Result comprarCarta(int idJogador, String nomeSala) {
		
		ObjectNode json = Json.newObject();
		
		Sala sala = sistema.buscarSala(nomeSala);
		Jogador jogador = sistema.buscarJogador(idJogador);
		Jogo jogo = jogos.get(sala.nome);
		
		if (jogo != null) {
			if (jogo.realizarJogada(jogador, null, Jogo.TIPO_JOGADA_COMPRAR)) {
				for (Jogador jogador_ : sala.jogadores) {
					jogador_.notificar2("jogo");
				}
				return ok(Json.toJson(jogo.getStatus()));
			}
			json.put("erro", "A jogada não foi realizada, pois eh inválida. Possiveis erros: Jogador não possui carta, a carta não pode ser jogada, o jogador não está na sala, não é a vez do jogador.");
		} else {
			json.put("erro", "Não foi encontrado jogo para a sala informada.");
		}
		
		return ok(json);
	}
	
	
	public static Result desistirJogo(int idJogador, String nomeSala) {
		
		ObjectNode json = Json.newObject();
		
		Sala sala = sistema.buscarSala(nomeSala);
		Jogador jogador = sistema.buscarJogador(idJogador);
		Jogo jogo = jogos.get(sala.nome);
		
		if (jogo != null) {
			if (jogo.realizarJogada(jogador, null, Jogo.TIPO_JOGADA_DESISTENCIA)) {
				for (Jogador jogador_ : sala.jogadores) {
					jogador_.notificar2("jogo");
				}
				return ok(Json.toJson(jogo.getStatus()));
			}
			json.put("erro", "A jogada não foi realizada, pois eh inválida. Possiveis erros: Jogador não possui carta, a carta não pode ser jogada, o jogador não está na sala, não é a vez do jogador.");
		} else {
			json.put("erro", "Não foi encontrado jogo para a sala informada.");
		}
		
		return ok(json);
	}
	
	
	public static Result desafiar(int idJogador, String nomeSala) {
		
		ObjectNode json = Json.newObject();
		
		Sala sala = sistema.buscarSala(nomeSala);
		Jogador jogador = sistema.buscarJogador(idJogador);
		Jogo jogo = jogos.get(sala.nome);
		
		if (jogo != null) {
			if (jogo.realizarJogada(jogador, null, Jogo.TIPO_JOGADA_DESAFIAR)) {
				for (Jogador jogador_ : sala.jogadores) {
					jogador_.notificar2("jogo");
				}
				return ok(Json.toJson(jogo.getStatus()));
			}
			json.put("erro", "A jogada não foi realizada, pois eh inválida. Possiveis erros: Jogador não possui carta, a carta não pode ser jogada, o jogador não está na sala, não é a vez do jogador.");
		} else {
			json.put("erro", "Não foi encontrado jogo para a sala informada.");
		}
		
		return ok(json);
	}
	
	
	public static Result index2() {
		Jogador jogador = new Jogador();
		return ok(index2.render("Texto qualquer"));
	}


}
